package com.ctshk.rpc.finance.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.CharUtil;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.booking.dto.SupplierOrderFinishPageDTO;
import com.ctshk.rpc.booking.dto.unsubscribe.page.SupplierUnsubscribePageDTO;
import com.ctshk.rpc.booking.req.SupplierOrderFinancePageReq;
import com.ctshk.rpc.booking.req.unsubscribe.page.SupplierUnsubscribeFinanceContactsPageReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.booking.service.ISupplierUnsubscribeService;
import com.ctshk.rpc.finance.dto.supplier.*;
import com.ctshk.rpc.finance.entity.FinanceSupplierReconciliation;
import com.ctshk.rpc.finance.entity.FinanceSupplierReconciliationDetail;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.mapper.FinancePaidInDetailMapper;
import com.ctshk.rpc.finance.mapper.FinanceSupplierReconciliationDetailMapper;
import com.ctshk.rpc.finance.mapper.FinanceSupplierReconciliationMapper;
import com.ctshk.rpc.finance.req.supplier.*;
import com.ctshk.rpc.finance.service.IFinanceSupplierReconciliationService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;


import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 财务供应商对账单 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-04-08
 */
@DubboService
public class FinanceSupplierReconciliationServiceImpl extends ServiceImpl<FinanceSupplierReconciliationMapper, FinanceSupplierReconciliation> implements IFinanceSupplierReconciliationService {

    @Autowired
    private FinanceSupplierReconciliationMapper supplierReconciliationMapper;
    @Autowired
    private FinanceSupplierReconciliationDetailMapper supplierReconciliationDetailMapper;
    @Autowired
    private FinancePaidInDetailMapper paidInDetailMapper;

    @DubboReference
    private ISysApprovalService sysApprovalService;

    @DubboReference
    private ISysUserService sysUserService;

    @DubboReference
    private ISupplierOrderService supplierOrderService;

    @DubboReference
    private ISupplierUnsubscribeService supplierUnsubscribeService;



    /**
     * 列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<SupplierReconciliationListDTO>> list(SupplierReconciliationListReq req) {
        Page<SupplierReconciliationListDTO> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        Page<SupplierReconciliationListDTO> page = supplierReconciliationMapper.queryListByCondition(iPage,req);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        page.getRecords().forEach(reconciliation -> {
            //查询创建人
//            UserDTO userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + reconciliation.getCreateId());
            UserDTO userDto = sysUserService.queryCacheUser(reconciliation.getCreateId());
            if (userDto != null){
                reconciliation.setCreateUserName(userDto.getFullName());
                reconciliation.setCreateUserDept(userDto.getDept());
            }
            //查询应付金额列表
            List<ReconciliationDetailDTO> detailList =  supplierReconciliationDetailMapper.queryDetailByReconciliationReconciliation(reconciliation.getId());
            if (detailList != null && detailList.size() > 0){
                reconciliation.setDetailList(detailList);
            }
        });
        PageResponse<SupplierReconciliationListDTO> result = new PageResponse<>(
                page.getRecords(),
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 详情
     *
     * @param req
     * @return
     */
    @Override
    public Result<SupplierReconciliationDTO> detail(SupplierReconciliationIdReq req) {
        //查询对账记录
        FinanceSupplierReconciliation reconciliation = getById(req.getReconciliationId());
        if (reconciliation == null || Objects.equals(reconciliation.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17027);
        }
        //返回数据
        SupplierReconciliationDTO dto = EntityUtil.copy(reconciliation,SupplierReconciliationDTO.class);
        //附件
        if (StringUtils.isNotBlank(reconciliation.getFilesJson())){
            dto.setFilesJson(JSON.parseArray(reconciliation.getFilesJson(), FileJson.class));
        }
        //查询创建人
        UserDTO userDto = sysUserService.queryCacheUser(reconciliation.getCreateId());
        if (userDto != null){
            dto.setCreateUserName(userDto.getFullName());
            dto.setCreateUserDept(userDto.getDept());
        }
        //对账明细列表
        QueryWrapper<FinanceSupplierReconciliationDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("reconciliation_id",reconciliation.getId());
        queryWrapper.eq("is_deleted",0);
        List<FinanceSupplierReconciliationDetail> detailList = supplierReconciliationDetailMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(detailList)){
            List<ReconciliationDetailReq> detailReqList = EntityUtil.copyList(detailList,ReconciliationDetailReq.class);
            dto.setDetailReqList(detailReqList);
        }
        return Result.success(dto);
    }

    /**
     * 新增/编辑对账单
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(SupplierReconciliationAddReq req) {
        //操作类型（1新增，2修改）
        int operateType = 1;
        FinanceSupplierReconciliation reconciliation = null;
        if (req.getReconciliationId() != null){
            //查询对账记录
            reconciliation = getById(req.getReconciliationId());
            if (reconciliation == null || Objects.equals(reconciliation.getIsDeleted(),1)){
                throw new BusinessException(SystemError.FINANCE_CHARGE_17027);
            }
            operateType = 2;
        }
        reconciliation = EntityUtil.copy(req,FinanceSupplierReconciliation.class);
        LocalDateTime now = LocalDateTime.now();
        //GDZ+年後2位+月日4位+時分秒6位+4位随机数字
        String reconciliationNumber = "GDZ"+ DateUtil.fmt(now,"yyMMddHHmmss"+ CharUtil.getRandomStr(4));
        reconciliation.setReconciliationNumber(reconciliationNumber);
        //附件
        List<FileJson> filesJson = req.getFilesJson();
        if (filesJson != null && filesJson.size() == 0){
            reconciliation.setFilesJson(JSON.toJSONString(filesJson));
        }
        reconciliation.setApprovalStatus(req.getType());
        if (operateType == 1){
            reconciliation.setId(SnowflakeIdWorker.nextId());
            reconciliation.setPayStatus(0);
            reconciliation.setCreateId(req.getUserId());
            reconciliation.setIsDeleted(0);
            //新增对账单
            boolean save = save(reconciliation);
            if (!save){
                throw new BusinessException(SystemError.SYS_437);
            }
        }else{
            reconciliation.setId(req.getReconciliationId());
            reconciliation.setModifiedId(req.getUserId());
            boolean bl = updateById(reconciliation);
            if (!bl){
                throw new BusinessException(SystemError.SYS_437);
            }
            //清空记录
            supplierReconciliationDetailMapper.cleanByReconciliation(reconciliation.getId(),req.getUserId());
        }
        //新增对账单详情
        if (req.getDetailReqList().size() == 0){
            throw new BusinessException(SystemError.SYS_428,"detailReqList");
        }
        List<FinanceSupplierReconciliationDetail> detailList = new ArrayList<>();
        for (ReconciliationDetailReq detailReq : req.getDetailReqList()){
            FinanceSupplierReconciliationDetail detail = EntityUtil.copy(detailReq,FinanceSupplierReconciliationDetail.class);
            detail.setId(SnowflakeIdWorker.nextId());
            detail.setReconciliationId(reconciliation.getId());
            detail.setGmtCreate(now);
            detail.setCreateId(req.getUserId());
            detail.setIsDeleted(0);
            detailList.add(detail);
        }
        //批量新增对账单详情
        Integer batch = supplierReconciliationDetailMapper.insertBatchSomeColumn(detailList);
        if (batch < detailList.size()){
            throw new BusinessException(SystemError.SYS_437);
        }
        //发起审批
        if (Objects.equals(req.getType(),2)){
            Long approvalId = startApproval(reconciliation.getId(), reconciliation.getId(), req.getUserId());
            reconciliation.setApprovalId(approvalId);
            boolean bl = updateById(reconciliation);
            if (!bl){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        return Result.success(reconciliation.getId());
    }

    /**
     * 提交审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result commit(SupplierReconciliationIdReq req) {
        //查询对账记录
        FinanceSupplierReconciliation reconciliation = getById(req.getReconciliationId());
        if (reconciliation == null || Objects.equals(reconciliation.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17027);
        }
        if (!Objects.equals(reconciliation.getApprovalStatus(),1)){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17028);
        }
        reconciliation.setApprovalStatus(2);
        reconciliation.setModifiedId(req.getUserId());
        //发起审批
        Long approvalId = startApproval(reconciliation.getId(), reconciliation.getId(),req.getUserId());
        reconciliation.setApprovalId(approvalId);
        boolean bl = updateById(reconciliation);
        boolean update = updateById(reconciliation);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(reconciliation.getId());
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result aproval(AprovalReq req) {
        QueryWrapper<FinanceSupplierReconciliation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getId());
        queryWrapper.eq("is_deleted",0);
        FinanceSupplierReconciliation reconciliation = supplierReconciliationMapper.selectOne(queryWrapper);
        if (reconciliation == null){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17027);
        }
        if (!Objects.equals(reconciliation.getApprovalStatus(),2)){
            throw new BusinessException(SystemError.FINANCE_BILL_17012);
        }
        reconciliation.setApprovalStatus(req.getType());
        reconciliation.setModifiedId(req.getUserId());
        if (Objects.equals(req.getType(),3)){
            //审批通过后的处理
            reconciliation.setPayStatus(1);
        }
        boolean update = updateById(reconciliation);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        Result<ApprovalCheckDTO> check = sysApprovalService.check(req.getId(), req.getUserId(), req.getType(), req.getComments());
        if (check == null || !check.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(reconciliation.getId());
    }

    /**
     * 申请供应商实付-选择供应商对账单列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<SupplierReconciliationChooseListDTO>> chooseList(SupplierReconciliationChooseListReq req) {
        Page<FinanceSupplierReconciliation> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceSupplierReconciliation> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(req.getReconciliationNumber()),"reconciliation_number",req.getReconciliationNumber());
        queryWrapper.between(req.getCreateTimeBegin() != null && req.getCreateTimeEnd() != null,"gmt_create",req.getCreateTimeBegin(),req.getCreateTimeEnd());
        queryWrapper.eq(req.getCreateId() != null,"create_id",req.getCreateId());
        Page<FinanceSupplierReconciliation> page = supplierReconciliationMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return Result.success(PageResponse.empty(page.getCurrent()));
        }
        List<SupplierReconciliationChooseListDTO> list = new ArrayList<>();
        page.getRecords().forEach(item -> {
            SupplierReconciliationChooseListDTO dto = EntityUtil.copy(item, SupplierReconciliationChooseListDTO.class);
            //查询创建人
            UserDTO userDto = sysUserService.queryCacheUser(item.getCreateId());
            if (userDto != null){
                dto.setCreateUserName(userDto.getFullName());
                dto.setCreateUserDept(userDto.getDept());
            }
            //查询应付金额列表
            List<ReconciliationDetailDTO> detailList =  supplierReconciliationDetailMapper.queryDetailByReconciliationReconciliation(item.getId());
            if (detailList != null && detailList.size() > 0){
                dto.setDetailList(detailList);
            }
            list.add(dto);
        });
        PageResponse<SupplierReconciliationChooseListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 删除
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result del(SupplierReconciliationIdReq req) {
        FinanceSupplierReconciliation reconciliation = getById(req.getReconciliationId());
        if (reconciliation == null || Objects.equals(reconciliation.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17027);
        }
        if (!Objects.equals(reconciliation.getApprovalStatus(),1) && !Objects.equals(reconciliation.getApprovalStatus(),4)){
            throw new BusinessException(SystemError.FINANCE_ERROR_17035);
        }
        //删除
        reconciliation.setIsDeleted(1);
        reconciliation.setModifiedId(req.getUserId());
        boolean del = updateById(reconciliation);
        if (!del){
            throw new BusinessException(SystemError.SYS_437);
        }
        //删除明细
        QueryWrapper<FinanceSupplierReconciliationDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("reconciliation_id",reconciliation.getId());
        queryWrapper.eq("is_deleted",0);
        Integer count = supplierReconciliationDetailMapper.selectCount(queryWrapper);
        Integer batch = supplierReconciliationDetailMapper.delByReconciliation(reconciliation.getId(),req.getUserId());
        if (!Objects.equals(count,batch)){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(reconciliation.getId());
    }

    /**
     * 供应商对账-供应商往来订单列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<SupplierOrderListDTO>> supplierOrderList(SupplierOrderListReq req) {
        Page<SupplierOrderListDTO> page = new Page<>(req.getPageNo(), req.getPageSize());
        List<SupplierOrderListDTO> list = null;
        if (Objects.equals(req.getType(),1)){
            //预订
            SupplierOrderFinancePageReq req1 = EntityUtil.copy(req,SupplierOrderFinancePageReq.class);
            PageResponse<SupplierOrderFinishPageDTO> resp = supplierOrderService.getFinanceContactsPage(req1);
            list = EntityUtil.copyList(resp.getRecords(),SupplierOrderListDTO.class);
        }else if (Objects.equals(req.getType(),2)){
            //退订
            SupplierUnsubscribeFinanceContactsPageReq req1 = EntityUtil.copy(req,SupplierUnsubscribeFinanceContactsPageReq.class);
            PageResponse<SupplierUnsubscribePageDTO> resp = supplierUnsubscribeService.getFinanceContactsPage(req1);
            if (CollectionUtils.isNotEmpty(resp.getRecords())){
                list = new ArrayList<>();
                for (SupplierUnsubscribePageDTO record : resp.getRecords()) {
                    SupplierOrderListDTO dto = new SupplierOrderListDTO();
                    dto.setReconciliationNumber(record.getCancellationNumber());
                    dto.setId(record.getId());
                    dto.setOrderType(record.getCancellationType());
                    dto.setOrderNumber(record.getSupplierOrderNumber());
                    dto.setCheckStatus(record.getVerifyStatus());
                    dto.setSupplierName(record.getSupplierName());
                    dto.setReserveTypeName(record.getReserveTypeName());
                    dto.setCreateUserDept(record.getCreate());
                    dto.setProductNumber(record.getProductNumber());
                    dto.setResourceProductName(record.getResourceInformation());
                    dto.setGmtCreate(record.getGmtCreate());
                    dto.setCurrency(record.getCurrency());
                    dto.setPayableAmount(record.getRefundAmount());
                    list.add(dto);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(list)){
            list.forEach(dto -> {
                //根据供应商订单ID查询对账单号
                String reconciliationNumber = supplierReconciliationDetailMapper.queryByOrderId(dto.getId());
                dto.setReconciliationNumber(reconciliationNumber);
            });
        }
        PageResponse<SupplierOrderListDTO> result = new PageResponse<>(
                list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(),
                page.getCurrent(),
                page.getSize());
        return Result.success(result);
    }

    /**
     * 根据供应商预订单ID批量获取（内部接口）
     *
     * @param idList
     * @return
     */
    @Override
    public Result<List<SupplierReconciliationAmountDTO>> getByOrderIdList(List<Long> idList) {
        //供应商订单付款统计
        List<SupplierReconciliationAmountDTO> dtoList = paidInDetailMapper.selectByOrderIdList(idList);
        return Result.success(dtoList);
    }


    /**
     * 发起审批流程
     * @param id
     * @param businessId
     * @param userId
     */
    private Long startApproval(Long id, Long businessId, Long userId) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.FINANCE.getCode(),
                    SysApprovalType.SUPPLIERPAIRS_FINANCE.getCode(), businessId,
                    userId, null, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }

}
